package com.webex.ta.hydra.plugin;

import com.webex.ta.hydra.CoreClassLoader;
import com.webex.ta.hydra.core.PropertyManager;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-9-28
 * Time: 10:37:42
 */
public class PluginJar {
    private String path;
    private Plugin plugin;
    private PluginJarClassLoader classLoader;

    private String[] resources;
    private String[] classes;
    private Properties pluginProps;

    public PluginJar(File jar) throws IOException {
        this.path = jar.getAbsolutePath();
        classLoader = new PluginJarClassLoader(CoreClassLoader.getInstance(), this);
//        classLoader.activate();
        init();
    }

    public void activate() throws IOException {
        classLoader.activate();
        if (plugin != null) {
            PropertyManager.getInstance().addPluginProps(pluginProps);
            String clazz = plugin.getClazz();
            if (clazz != null) {
                try {
                    HydraPlugin plg = (HydraPlugin) Class.forName(clazz).newInstance();
                    plg.activate();
                } catch (Exception ignore) {
                    ignore.printStackTrace();
                }
            }
            plugin.setActivated(true);
        }
    }

    public void deactivate() throws IOException {
        classLoader.deactivate();
        if (plugin != null) {
            String clazz = plugin.getClazz();
            if (clazz != null) {
                try {
                    HydraPlugin plg = (HydraPlugin) Class.forName(clazz).newInstance();
                    plg.deactivate();
                } catch (Exception ignore) {
                    ignore.printStackTrace();
                }
            }
            plugin.setActivated(false);
        }
    }

    private void init() throws IOException {
        classLoader.activate();
        List<String> classes = new LinkedList<String>();
        List<String> resources = new LinkedList<String>();
        ZipFile zip = new ZipFile(path);
        Enumeration<? extends ZipEntry> itr = zip.entries();
        pluginProps = new Properties();
        while (itr.hasMoreElements()) {
            ZipEntry entry = itr.nextElement();
            if ("plugin.meta".equals(entry.getName())) {
                try {
                    plugin = new Plugin(this);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (entry.getName().endsWith(".properties") ||
                entry.getName().endsWith(".props")) {
                try {
                    pluginProps.load(classLoader.getResourceAsStream(entry.getName()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            String name = entry.getName();
            if (name.endsWith(".class")) {
                String className = fileToClass(name);
                classes.add(className);
            } else {
                resources.add(name);
            }

            this.classes = classes.toArray(new String[classes.size()]);
            this.resources = resources.toArray(new String[resources.size()]);
        }
        zip.close();
        classLoader.deactivate();
//        activate();


    }

    private static String fileToClass(String name) {
        char[] clsName = name.toCharArray();
        for (int i = clsName.length - 6; i >= 0; i--)
            if (clsName[i] == '/')
                clsName[i] = '.';
        return new String(clsName, 0, clsName.length - 6);
    }

    String[] getClasses() {
        return classes;
    }

    public String[] getResources() {
        return resources;
    }

    public String getPath() {
        return path;
    }

    public Plugin getPlugin() {
        return plugin;
    }

    public PluginJarClassLoader getClassLoader() {
        return classLoader;
    }
}
